在Java 5出現泛型之後,開發人員開始可以為類別、方法或interface添加型別參數(type parameters)(ex: List<Integer>
),指定實體化成物件之後的參數型別,而這些加了型別參數的類別、方法或interface統稱為泛型類型(generic types),更彈性的接受不同型別的參數來擴充功能。
在過去還沒有泛型的時候,沒有型別參數,只能使用原始類型(raw types)(ex: List
),所有參數的型別在宣告時不先指定,等到後面要使用時在手動進行強制轉型,就像下面List
的範例,add
的時候任意放入各種型別的參數,get
的時候在強制轉型。
import java.util.ArrayList;
import java.util.List;
public class TestList {
public static void main(String[] args) {
// 宣告一個List,沒有型別參數
List list = new ArrayList();
// 添加element到 List 中
list.add("Hello");
list.add("World");
list.add(123); // 可以添加不同型別的元素
// 從List中取出element時,需要手動進行型別轉換
String item1 = (String) list.get(0);
String item2 = (String) list.get(1);
int number = (Integer) list.get(2);
System.out.println(item1);
}
}
雖然到了Java 14,為了讓舊有程式碼可以繼續運作,還有繼續支援原始類型,但是不建議在Java 5出現泛型之後的程式碼,繼續使用原始類型,因為原始類型在強制轉型的時候,如果給錯型別,在runtime才會跳出錯誤,會讓開發人員不好debug。舉例來說,如果加進List
的物件是Integer
,強制轉型的時候卻轉成String
,runtime才會跳出java.lang.ClassCastException
。
import java.util.ArrayList;
import java.util.List;
public class TestList {
public static void main(String[] args) {
// 宣告一個List,沒有指定泛型類型
List list = new ArrayList();
// 添加元素到 List 中
list.add("Hello");
list.add("World");
list.add(123); // 可以添加不同類型的元素
// 從 List 中取出元素時,需要手動進行類型轉換
String item1 = (String) list.get(0);
String item2 = (String) list.get(1);
String number = (String) list.get(2); //錯誤的型別
System.out.println(item1);
}
}
有了泛型之後的Java,為了提醒開發人員有型別錯誤的風險,編譯的時候,compiler也會發出警告,提醒開發人員程式碼有unchecked和unsafe的操作,可以讓開發人員想想要不要修改程式碼,但如果無法改變事實,不得不繼續背著老舊的包袱,又不想看到這個煩人的警告XDDD,可以在編譯的時候加-Xlint:unchecked
(ex: javac TestList.java -Xlint:unchecked
)忽略。